﻿/* 
    Copyright (c) 2010 Microsoft Corporation.  All rights reserved.
    Use of this sample source code is subject to the terms of the Microsoft license 
    agreement under which you licensed this sample source code and is provided AS-IS.
    If you did not accept the terms of the license agreement, you are not authorized 
    to use this sample source code.  For the terms of the license, please see the 
    license agreement between you and Microsoft.
    
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;


namespace FillRateTest
{
    /// <summary>
    /// This sample allows you to dynamically add animated rectangles to the page to observe how the application's frame rate
    /// is related to the number of pixels drawn for each frame. Also, this sample uses buttons placed in the corners of the page
    /// which can be toggled between hidden and visible. This allows you to see how the frame rate is affected by the UI elements.
    /// You can see that performance is better when the UI elements are grouped together, causing fewer pixels to be drawn.
    /// </summary>
    public partial class MainPage : PhoneApplicationPage
    {
        private List<Rectangle> rectList;
        private List<Color> rectColors;
        Random _rand;
        const int _duration = 3000;
        int _nPixels = 0;
        double _dScreens = 0.0;
        private bool _isHidden = false;
        /// <summary>
        /// Constructor. The frame rate counter is enabled. The rectangle and color lists are initialized.
        /// </summary>
        public MainPage()
        {
            InitializeComponent();

            // Turn on the frame rate counter
            Application.Current.Host.Settings.EnableFrameRateCounter = true;


            rectList = new List<Rectangle>();
            rectColors = new List<Color>() { Colors.Blue, Colors.Red, Colors.Green, Colors.Cyan, Colors.Magenta, Colors.Orange, Colors.Purple, Colors.Yellow, Colors.Brown, Colors.Gray };
            _rand = new Random();
        }

        /// <summary>
        /// Click handler for the Add button. This method creates a new rectangle, animates it, and updates the screen and total TextBlocks
        /// to display the number of screens being drawn for each frame.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void addBtn_Click(object sender, RoutedEventArgs e)
        {

            // A new Rectangle is created and assigned a random color from the list of colors.
            Rectangle newRect = new Rectangle();
            newRect.Height = 800;
            newRect.Width = 60;
            newRect.Fill = new SolidColorBrush(rectColors[_rand.Next(10)]);

            // A translation animation is created using the generateTranslateAnimation helper method.
            TransformGroup rectTransformGroup = new TransformGroup();
            TranslateTransform rectTranslate = new TranslateTransform();
            DoubleAnimation rectTranslateX = generateTranslateAnimation();

            // The target of the animation is set.
            Storyboard.SetTarget(rectTranslateX, rectTranslate);
            Storyboard.SetTargetProperty(rectTranslateX, new PropertyPath(TranslateTransform.XProperty));

            // The translation is added to the transform group and then set to be the RenderTransform of the new rectangle.
            rectTransformGroup.Children.Add(rectTranslate);
            newRect.RenderTransform = rectTransformGroup;

            // The translation animation is added to a Storyboard and the Storyboard is started to begin the animation.
            Storyboard rectStoryboard = new Storyboard();
            rectStoryboard.Children.Add(rectTranslateX);
            rectStoryboard.Begin();

            // The new rectangle is added to the list of rectangles
            rectList.Add(newRect);

            // The pixels in the rectangle (which is 800 x 60 pixels) are added to the total pixel count.
            // 800 x 60 is 1/8 of the size of the screen. So for each rectangle added, .125 is added to the 
            // number of screens being drawn.
            _nPixels += 48000;
            _dScreens += 0.125;

            // In the screens TextBlock, show the number of screens being drawn with each frame just for the rectangles.
            screens.Text = _dScreens.ToString();

            // In the total TextBlock, show the total number of screens being drawn, including the rectangles and the buttons.
            // If the buttons at the bottom of the screen are hidden, an additional .07 screens are drawn for each frame.
            // If the buttons at the bottom are not hidden, .9 additional screens are drawn.
            if (_isHidden)
            {
                total.Text = (_dScreens + 0.07).ToString();
            }
            else
            {
                total.Text = (_dScreens + 0.9).ToString();
            }

            // Finally, add the new rectangle to the LayoutRoot.
            this.LayoutRoot.Children.Add(newRect);

        }
        /// <summary>
        /// The click handler for the delete button. This method deletes one rectangle off of the end of the list and 
        /// updates the screen and total TextBlocks to display the number of screens being drawn for each frame.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void deleteBtn_Click(object sender, RoutedEventArgs e)
        {
            // Make sure there is at least one rectangle.
            if (rectList.Count >= 1)
            {
                // Remove the rectangle from the LayoutRoot and from the app's list of rectangles.
                this.LayoutRoot.Children.Remove(rectList[rectList.Count - 1]);
                rectList.Remove(rectList[rectList.Count - 1]);

                // Force a layout update. All computed sizes will be reevaluated.
                UpdateLayout();

                // The pixels in the rectangle (which is 800 x 60 pixels) are subtracted from the total pixel count.
                // 800 x 60 is 1/8 of the size of the screen. So for each rectangle deleted, .125 is subtracted from the 
                // number of screens being drawn.
                _nPixels -= 48000;
                _dScreens -= 0.125;

                // In the screens TextBlock, show the number of screens being drawn with each frame just for the rectangles.
                screens.Text = _dScreens.ToString();

                // In the total TextBlock, show the total number of screens being drawn, including the rectangles and the buttons.
                // If the buttons at the bottom of the screen are hidden, an additional .07 screens are drawn for each frame.
                // If the buttons at the bottom are not hidden, .9 additional screens are drawn.
                if (_isHidden)
                {
                    total.Text = (_dScreens + 0.07).ToString();
                }
                else
                {
                    total.Text = (_dScreens + 0.9).ToString();
                }
            }

        }

        /// <summary>
        /// Click handler for the Hide button. This method hides all of the buttons except for the Show button to 
        /// demonstrate how the fill rate is affected.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void hideBtn_Click(object sender, RoutedEventArgs e)
        {
            showBtn.Visibility = Visibility.Visible;
            hideBtn.Visibility = Visibility.Collapsed;
            addBtn.Visibility = Visibility.Collapsed;
            deleteBtn.Visibility = Visibility.Collapsed;

            _isHidden = true;

            // If the buttons at the bottom of the screen are hidden, an additional .07 screens are drawn for each frame.
            total.Text = (_dScreens + 0.07).ToString();
        }
        /// <summary>
        /// Click handler for the Show button. This method shows all of the buttons except for the Show button to 
        /// demonstrate how the fill rate is affected.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void showBtn_Click(object sender, RoutedEventArgs e)
        {
            showBtn.Visibility = Visibility.Collapsed;
            hideBtn.Visibility = Visibility.Visible;
            addBtn.Visibility = Visibility.Visible;
            deleteBtn.Visibility = Visibility.Visible;

            _isHidden = false;

            // If the buttons at the bottom are not hidden, .9 additional screens are drawn for each frame.
            total.Text = (_dScreens + 0.9).ToString();
        }

        
        /// <summary>
        /// This helper method creates a new animation that moves the target horizontally from one side of the screen
        /// to the other, then reverses and repeats indefinitely.
        /// </summary>
        /// <returns></returns>
        public DoubleAnimation generateTranslateAnimation()
        {

            DoubleAnimation rectTranslate = new DoubleAnimation();

            rectTranslate.Duration = new TimeSpan(0, 0, 0, 0, _duration);
            rectTranslate.From = 0;
            rectTranslate.To = 480;
            rectTranslate.AutoReverse = true;
            rectTranslate.RepeatBehavior = RepeatBehavior.Forever;

            return rectTranslate;
        }

        
    }
}
